<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。JCAT 由中国团队开发维护。
//  正在使用的这个版本是：0.4.0 / SVN信息: $Id: class.JCAT_RequestDispatcher.php 1494 2009-03-19 12:53:43Z alee $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [下载(HTTP)] http://code.google.com/p/jcat-php/downloads/list
//    [下载(svn)] svn checkout http://jcat-php.googlecode.com/svn/branches/0.4.0/Framework/ JCAT0.4
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.com/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.com/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/


class JCAT_RequestDispatcher 
{	
	const EXCEPID_NO_REQUEST = 32541 ;
	
	const EXCEPID_NOT_A_CONTROLLER = 32542 ;
	
	/**
	 * Description
	 *
	 * @access	public
	 * @return	void
	 */
	public function JCAT_RequestDispatcher(JCAT_Request $aUsrRequest=null)
	{
		$this->SetRequest($aUsrRequest? $aUsrRequest: JCAT_Request::GetGlobalInstance()) ;
	}

	
	/**
	 * 设置对象属性 aRequest
	 *
	 * @access	public
	 * @param	$aRequest		JCAT_Request	aRequest
	 * @return	old_value
	 */
	public function SetRequest(JCAT_Request $aRequest)
	{
		$this->aRequest = $aRequest ;
	}
	
	/**
	 * 取得对象属性 aRequest
	 *
	 * @access	public
	 * @return	JCAT_Request
	 */
	public function GetRequest()
	{
		return $this->aRequest ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$sAlias
	 * @param	$sControllerClass
	 * @return	void
	 */
	public function RegisterControllerAlias($sAlias,$sControllerClass)
	{
		if( $sAlias!=$sControllerClass and JCAT_Global::HasImplementedTo($sAlias,'JCAT_IHTTPPublicController') )
		{
			throw new JCAT_Exception(JCAT_Language::SentenceEx(
				'无法注册控制器别名：%s，已经存在同名的控制器类。'
				, 'JCAT', null
				, $sAlias
			)) ;
		}
		
		$this->arrControllerAliasies[$sAlias] = $sControllerClass ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$sAlias
	 * @return	string
	 */
	public function GetControllerClassByAlias($sAlias)
	{
		return isset($this->arrControllerAliasies[$sAlias])?
						$this->arrControllerAliasies[$sAlias] : null ;
	}
	
	
	/**
	 * set a default controller, if request has no specified controller, use this
	 *
	 * @access	public
	 * @param	$sDefaultController
	 * @return	void
	 */
	public function SetDefaultController($sDefaultController)
	{
		JCAT_ASSERT::ASSERT_ISTHESE($sDefaultController,array('JCAT_IController','null')
				, JCAT_Language::SentenceEx('%s::%s 参数 $sDefaultController 必须实现 JCAT_IController 接口。', 'JCAT', null
				, __CLASS__
				, __FUNCTION__)
		) ;

		$this->sDefaultController = $sDefaultController ;
	}
	
	/**
	 * respond the user request
	 * if no controller be responded, return false; otherwise return true 
	 *
	 * @access	public
	 * @param 	$aThrowExcep=true	bool	throw a exception if neither default controller nor specify a controller
	 * @return	bool
	 */
	public function Respond($aThrowExcep=true)
	{
		$sControllerName = $this->GetRequestController($aThrowExcep) ;
		if(!$sControllerName)
		{
			return false ;
		}

		// run it
		$this->RunController($sControllerName) ;
		
		return true ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param 	$aThrowExcep=true	bool	throw a exception if neither default controller nor specify a controller
	 * @return	string
	 */
	public function GetRequestController($aThrowExcep=true)
	{
		// get user request
		$aRequest = $this->GetRequest() ;
		
		// get controller which user request
		if( !$sControllerName = $aRequest->GetRequestController() )
		{
			if( $this->sDefaultController )
			{
				$sControllerName = $this->sDefaultController ;
			}
		
			else 
			{
				if( $aThrowExcep )
				{
					throw new JCAT_Exception(JCAT_Language::SentenceEx(
						'当前请求既没有指定控制器，也没有定义缺省控制器。'
						, 'JCAT', null
					),self::EXCEPID_NO_REQUEST) ;
				}
				
				return null ;
			}
		}
		
		// get controller class by alias
		$sControllerNameByAlias = $this->GetControllerClassByAlias($sControllerName) ;
		$sControllerName = $sControllerNameByAlias? $sControllerNameByAlias: $sControllerName ;
		
		if( !JCAT_Global::HasImplementedTo($sControllerName,'JCAT_IController') )
		{
			if( $aThrowExcep )
			{
				throw new JCAT_Exception(JCAT_Language::SentenceEx(
					'正在请求一个未知的控制器：%s'
					, 'JCAT', null ,$sControllerName
				),self::EXCEPID_NOT_A_CONTROLLER) ;
			}
			
			else 
			{
				return null ;
			}
		}
		
		return $sControllerName ;
	}
	
	/**
	 * run a controller
	 *
	 * @access	public
	 * @param	$Controller
	 * @return	void
	 */
	public function RunController($Controller,$bAsTop=true)
	{
		JCAT_ASSERT::ASSERT_ISTHESE($Controller,array('string','object'));
		
		if( JCAT_Request::IsHTTPRequest() and !JCAT_Global::HasImplementedTo($Controller,'JCAT_IHTTPPublicController') )
		{
			throw new JCAT_Exception(JCAT_Language::SentenceEx(
				"正在请求的控制器(%s)没有实现 JCAT_IHTTPPublicController 接口，无法通过 HTTP 直接访问。"
				, 'JCAT', null
				, (is_object($Controller)? get_class($Controller): $Controller)
			)) ;
		}
		
		// 创建控制器 
		$aController = is_object($Controller)? $Controller: new $Controller(null,null,$this->GetRequest()) ;
		
		// run
		$aController->MainRun() ;
	}
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @var		array
	 */
	private $arrControllerAliasies = array() ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @var		string
	 */
	private $sDefaultController ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @var		JCAT_Request
	 */
	private $aUsrRequest ;
}

?>